/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2007，所有权利保留。
 * 
 * 项目名：	rumba
 * 文件名：	FilterDialog.java
 * 模块说明：	
 * 修改历史：
 * Dec 6, 2007 - lxm - 创建。
 */
package com.hd123.rumba.gwt.cpnts.filter.client;

import java.util.Set;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.hd123.rumba.gwt.base.client.exception.ClientBizException;
import com.hd123.rumba.gwt.base.client.util.ObjectUtil;

/**
 * 筛选对话框 | UI
 * <p>
 * 
 * @author lxm
 * 
 */
public class FilterDialog extends DialogBox {

  public FilterDialog() {
    super();

    this.setText("筛选");
    DockPanel panel = new DockPanel();
    panel.setSpacing(4);
    panel.setWidth("100%");

    Widget wExpression = this.draw_wExpression();
    panel.add(wExpression, DockPanel.CENTER);

    Widget wCommands = this.draw_wCommands();
    panel.add(wCommands, DockPanel.SOUTH);
    panel.setCellHorizontalAlignment(wCommands, DockPanel.ALIGN_RIGHT);

    Widget wSummary = this.draw_wSummary();
    panel.add(wSummary, DockPanel.SOUTH);

    Widget wAndOr = this.draw_wAndOr();
    panel.add(wAndOr, DockPanel.SOUTH);
    panel.setCellHorizontalAlignment(wAndOr, DockPanel.ALIGN_CENTER);

    this.setWidget(panel);
  }

  public void show() {
    super.show();
    showing = true;
    // TODO 从服务器取得buffer，刷新界面数据显示。
  }

  public void hide() {
    showing = false;
  }

  // --------------------------------------------------------------------------
  // 数据部分
  // --------------------------------------------------------------------------

  private boolean showing = false;
  /** 可被在系统中运行的表达式。符合hql语法，可被用于where子句。 */
  private String runnableExp = "";
  /** 用户友好的表达式，与当前{@link #runnableExp}对应。 */
  private String friendlyExp = "";
  /** 自动扩展深度。>=0且<=3的整数，默认为1。 */
  private int expandDeep = 1;
  /** 实体信息缓冲 */
  private EntityInfoBuffer buffer = new EntityInfoBuffer();

  /**
   * 清除所加入的所有数据实体列表。
   * 
   */
  public void clearEntities() throws ClientBizException {
    this.checkToUpdateBuffer();
    buffer.clear();
  }

  /**
   * 添加一个数据实体。
   * 
   * @param entityClassName
   *          指定数据实体的类名。不允许null。若指定的数据实体已经存在，则将导致修改指定的别名。
   * @param alias
   *          指定将被用于表达式的别名。允许null，表示不使用别名，将导致在返回的表达式中直接采用类名。
   * @throws ClientBizException
   */
  public void addEntity(String entityClassName, String alias) throws ClientBizException {
    ObjectUtil.checkParameterNotNull(entityClassName, "entityClassName");
    this.checkToUpdateBuffer();
    this.buffer.add(entityClassName, alias);
  }

  /**
   * 删除指定的数据实体。
   * <p>
   * 
   * 指定的数据实体若不存在，则不做任何事。
   * 
   * @param entityClassName
   *          指定的数据实体类名。允许null。
   * @throws ClientBizException
   */
  public void removeEntity(String entityClassName) throws ClientBizException {
    this.checkToUpdateBuffer();
    EntityInfoBuffer.Record record = this.buffer.get(entityClassName);
    if (record != null)
      this.buffer.remove(record);
  }

  /**
   * 判断是否已经包含了指定的数据实体。
   * 
   * @param entityKey
   *          指定的数据实体类名或别名。允许null，将始终返回false。
   * @return
   * @throws ClientBizException
   */
  public boolean containsEntity(String entityKey) throws ClientBizException {
    return this.buffer.contains(entityKey);
  }

  /**
   * 取得所包含的数据实体集合。
   * 
   * @return set of String。包含数据实体类名的集合。若没有包含任何的数据实体，则返回空的集合。
   * @throws ClientBizException
   */
  public Set entitiesSet() throws ClientBizException {
    return this.buffer.classNameSet();
  }

  /**
   * 取得数据实体所对应的别名。
   * 
   * @param entityClassName
   *          指定的数据实体类名。允许null，将始终返回null。
   * @return 返回所对应的别名，若不存在指定的数据实体，则返回null。
   * @throws ClientBizException
   */
  public String getAliasByEntity(String entityClassName) throws ClientBizException {
    return this.buffer.get(entityClassName).getAlias();
  }

  /**
   * 根据别名取得对应的数据实体。
   * 
   * @param alias
   *          指定的别名。允许null，将始终返回null。
   * @return 返回数据实体的类名，若找不到则返回null。
   * @throws ClientBizException
   */
  public String getEntityByAlias(String alias) throws ClientBizException {
    return this.buffer.get(alias).getClassName();
  }

  /** 自动扩展深度。>=0且<=3的整数，默认为1。 */
  public int getExpandDeep() {
    return expandDeep;
  }

  /** 自动扩展深度。>=0且<=3的整数，默认为1。 */
  public void setExpandDeep(int expandDeep) throws ClientBizException {
    if (expandDeep < 0 || expandDeep > 3)
      throw new ClientBizException("属性expandDeep必须是0到3之间的整数。(" + expandDeep + ")");
    this.expandDeep = expandDeep;
  }

  /** 用户友好的表达式，与当前{@link #runnableExp}对应。 */
  public String getFriendlyExp() {
    return friendlyExp;
  }

  /** 可被在系统中运行的表达式。符合hql语法，可被用于where子句。 */
  public String getRunnableExp() {
    return runnableExp;
  }

  /** 可被在系统中运行的表达式。符合hql语法，可被用于where子句。 */
  public void setRunnableExp(String expression) {
    this.runnableExp = expression;
  }

  /**
   * 实体信息缓冲
   * 
   * @return
   */
  EntityInfoBuffer getBuffer() {
    return this.buffer;
  }

  /** 检查是否允许修改{@link #buffer} */
  private void checkToUpdateBuffer() throws ClientBizException {
    if (showing)
      throw new ClientBizException("对话框已被打开，操作被禁止。");
  }

  // --------------------------------------------------------------------------
  // 用户界面部分
  // --------------------------------------------------------------------------

  private Button btnOk;

  private class Listener_btnOk implements ClickListener {
    public void onClick(Widget sender) {
      // TODO
    }
  }

  private Button btnCancel;

  private class Listener_btnCancel implements ClickListener {
    public void onClick(Widget sender) {
      // TODO
    }
  }

  private TextArea txtSummary;

  private class Listener_txtSummary implements ChangeListener {
    public void onChange(Widget sender) {
      // TODO
    }
  }

  private Button btnAddAnd;

  private class Listener_btnAddAnd implements ClickListener {
    public void onClick(Widget sender) {
      // TODO
    }
  }

  private Button btnAddOr;

  private class Listener_btnAddOr implements ClickListener {
    public void onClick(Widget sender) {
      // TODO
    }
  }

  /** 表达式左项 */
  private ExpLeftCmpst wExpLeft;
  /** 表达式运算符 */
  private ExpOperatorCmpst wExpOperator;
  /** 表达式右项 */
  private ExpRightCmpst wExpRight;

  private Widget draw_wCommands() {
    HorizontalPanel panel = new HorizontalPanel();
    panel.setSpacing(5);

    btnOk = new Button("确定", new Listener_btnOk());
    panel.add(btnOk);
    btnCancel = new Button("取消", new Listener_btnCancel());
    panel.add(btnCancel);

    return panel;
  }

  private Widget draw_wSummary() {
    VerticalPanel panel = new VerticalPanel();
    panel.setSpacing(2);

    panel.add(new Label("筛选条件："));

    txtSummary = new TextArea();
    txtSummary.setVisibleLines(5);
    DOM.setStyleAttribute(txtSummary.getElement(), "width", "100%");
    txtSummary.addChangeListener(new Listener_txtSummary());
    panel.add(txtSummary);

    return panel;
  }

  private Widget draw_wAndOr() {
    HorizontalPanel panel = new HorizontalPanel();
    panel.setSpacing(5);

    btnAddAnd = new Button("加入“和”条件", new Listener_btnAddAnd());
    panel.add(btnAddAnd);

    btnAddOr = new Button("加入“或”条件", new Listener_btnAddOr());
    panel.add(btnAddOr);

    return panel;
  }

  private Widget draw_wExpression() {
    Grid grid = new Grid(2, 3);
    grid.setCellSpacing(2);
    grid.setWidth("100%");

    grid.setText(0, 0, "表达式左项");
    wExpLeft = new ExpLeftCmpst(this);
    grid.setWidget(1, 0, wExpLeft);

    grid.setText(0, 1, "比较运算");
    wExpOperator = new ExpOperatorCmpst(this);
    grid.setWidget(1, 1, wExpOperator);

    grid.setText(0, 2, "表达式右项");
    wExpRight = new ExpRightCmpst(this);
    grid.setWidget(1, 2, wExpRight);

    return grid;
  }
}
